#include <windows.h>
#include <stdio.h>
#include <dshow.h>

int main(int argc, char** argv)
{
    HRESULT hr;
    ICreateDevEnum *pSysDevEnum = NULL;

    printf("start\n");

    CoInitialize(NULL);

    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum);

    if (FAILED(hr))
    {
        printf("hr: %X\n", hr);
        goto out;
    }

    // Obtain a class enumerator for the video compressor category.
    IEnumMoniker *pEnumCat = NULL;
    hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);

    if (hr != S_OK) 
    {
        printf("hr: %X\n", hr);
        goto out;
    }
     
    // Enumerate the monikers.
    IMoniker *pMoniker = NULL;
    ULONG cFetched;
    while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
    {
        IPropertyBag *pPropBag;
        hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
        if (SUCCEEDED(hr))
        {
            // To retrieve the filter's friendly name, do the following:
            VARIANT varName;
            VariantInit(&varName);
            hr = pPropBag->Read(L"FriendlyName", &varName, 0);
            if (SUCCEEDED(hr))
            {
                printf("var: %S\n", varName.bstrVal);
            }
            VariantClear(&varName);

            // To create an instance of the filter, do the following:
            IBaseFilter *pFilter;
            hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter);
            // Now add the filter to the graph. 
            //Remember to release pFilter later.
            pPropBag->Release();
        }
        pMoniker->Release();
    }

out:
    if (pEnumCat != NULL)
        pEnumCat->Release();
    if (pSysDevEnum != NULL)
        pSysDevEnum->Release();
    
    return 0;
}
